CloudWatch EventsとLambdaでDynamoDBのテーブルを定期作成する
こんにちは、菊池です。
やりたいこと
DynamoDBのテーブルを月ごとに分けて利用している環境で、以下のオペレーションを定期的に自動で実行したいというケースを想定しています。
- 前月のテーブルのRCU/WCUを下げる
- 翌月のテーブルを作成する
DynamoDBではテーブルが存在するだけで、割り当てたRCU/WCU分の利用料が発生します。新しいテーブルは必要になるタイミングで作成し、古くなってアクセス頻度が減ったテーブルは割り当てるRCU/WCUを小さくすることでコストを抑えることができます。
上記のオペレーションを実行するLambda関数を作成し、CloudWatch Eventsで自動実行することで、この要件を実現します。
環境構築
テーブル自動作成
まずはテーブルを定期的に作成する環境です。
Lambda関数の作成
DynamoDBのテーブルを新規に作る関数を作成します。
トリガーは後から設定しますので、何もせず次に進みます。
関数名を入力し、ランタイムはPython 3.6にしました。
以下のコードをPython 3.6のランタイムで作成します。実行日時の10日後の年月でtable_yyyymm
という名称のテーブルを作成するコードです。同名のテーブルが存在する場合には何もしません。
import boto3 import datetime def lambda_handler(event, context): dynamodb = boto3.client('dynamodb') WCU = event['wcu'] RCU = event['rcu'] now = datetime.datetime.now() next_month = now + datetime.timedelta(days=10) new_table_name = "table_" + next_month.strftime("%Y%m") tables = dynamodb.list_tables()['TableNames'] if new_table_name not in tables: newtable = dynamodb.create_table( AttributeDefinitions=[ { 'AttributeName': 'id', 'AttributeType': 'S' } ], TableName = new_table_name, KeySchema=[ { 'AttributeName': 'id', 'KeyType': 'HASH' } ], ProvisionedThroughput={ 'ReadCapacityUnits': RCU, 'WriteCapacityUnits': WCU } ) print("New table is created.") else: print("New table is already exist.") return 0
続いて、IAMロールの選択です。あらかじめ作成していなければ、新規に作成します。
利用するIAMロールには、AmazonDynamoDBFullAccessの管理ポリシーをアタッチしておきます。
関数ができたら、テストイベントを入力してテストしてみます。JSONで指定したwcu
、rcu
の値でテーブルが作成されます。
{ "wcu": 5, "rcu": 5 }
実行して成功すれば、テーブルが作成されているはずです。テーブル名は、table_yyyymm
となります。今回のコードでは実行日+10日の月で作成されますので、実行タイミングに合わせて調整しましょう。
CloudWatch Eventsの設定
続いて、定期実行させるためのイベントを作成します。CloudWatchから、[イベント]-[ルールの作成]を選びます。
イベントソースに、[スケージュール]、[Cron式]を選択します。今回は毎月25日の日本時間9時に実行したいので、0 0 25 * ? *
と入力します。設定パターンはこちらを参照ください。イベントターゲットは、作成したLambda関数を選択し、入力にwcu、rcuの値を指定するJSONを設定します。
イベントルール名を指定し、作成します。
WCU/RCUの自動変更
続いて、古くなったテーブルのキャパシティを変更する関数を作成します。
Lambda関数
同様に、Python3.6の関数を作成します。table_yyyymm
という名称のテーブルのRCU/WCUを指定した値に変更するコードです。yyyymm
は実行日の10日前の年月になりますので、実行タイミングによって調整しましょう。対象のテーブルが存在しない場合には何もしません。
import boto3 import datetime def lambda_handler(event, context): dynamodb = boto3.client('dynamodb') TARGET_WCU = event['decreace_target_wcu'] TARGET_RCU = event['decreace_target_rcu'] now = datetime.datetime.now() last_month = now - datetime.timedelta(days=10) old_table_name = "table_" + last_month.strftime("%Y%m") tables = dynamodb.list_tables()['TableNames'] if old_table_name in tables: old_table = dynamodb.describe_table( TableName=old_table_name ) wcu = old_table['Table']['ProvisionedThroughput']['WriteCapacityUnits'] rcu = old_table['Table']['ProvisionedThroughput']['ReadCapacityUnits'] if rcu == TARGET_RCU and wcu == TARGET_WCU: print("Old table is not modified.") else: modify = dynamodb.update_table( TableName= old_table_name, ProvisionedThroughput={ 'ReadCapacityUnits': TARGET_RCU, 'WriteCapacityUnits': TARGET_WCU } ) print("Old table CU is modified.") else: print("Old table is not exist.") return 0
テストイベントで、設定するwcu/rcuを指定し、テストしてみましょう。
{ "decreace_target_wcu": 5, "decreace_target_rcu": 5 }
CloudWatch Eventsの設定
続いて、定期実行させるためのイベントを作成します。先程と同様に、CloudWatchから、[イベント]-[ルールの作成]を選びます。
設定の方法は同じです。こちらは毎月5日の日本時間9時に実行しますので、0 0 5 * ? *
と入力します。ターゲットのLambda関数と入力のJSONを設定します。
以上で環境が準備できました。それぞれ、CloudWatch Eventsで指定した日時になれば実行されます。
最後に
以上です。
定期的に実行するオペレーションは、Lambda + CloudWatch Eventsを使うことで自動化することができます。
なお、今回紹介した構成はあくまでサンプルですので、運用環境に適用する際には、エラー発生時の検知や、対応方法も併せて検討しましょう。